
#include <mpi.h>
#include <iostream>
#include <cstdlib>
#include <string>   // pour std::string
#include <fstream>  // pour les fichiers
using namespace std;



int sommeTableau(int * tableau , int nbproc,int taille){
  int res=0;
  for(int i=0; i<taille;i++){
    res+=tableau[i];
  }
  return res;
}

//1 -> [1]

void rassemblerResultat(int ** resPhaseIII, int pid,int nrows, int ncols,int nbprocs){
  int * resultatCase;
  resultatCase = new int * [nbprocs];
	for(int i=0; i< ncols ;i++){
		resultatCase[i] = new int[ncols];
	}
	//for(int 
	  //recuperer le tableau resultat 
      for(int lig=0 ; lig<nrows ; lig++){
	for(int col = 0; col< ncols; col++){
	    //Le gather va créer un tableau qui contient toutes les cases i des différents processeurs 0 0 0 2
	    MPI_Gather(resPhaseIII[lig][col],1,MPI_INT,resultatCase,1,MPI_INT,0,MPI_COMM_WORLD);
	    //Apres le gather, dans le tableau resultatCase, on a le resultat de tous les processeurs
	    //On fais une somme pour récupérer la valeur qui a été trouvée par un des processeur
	    resPhaseIII[lig][col]==sommeTableau(resultatCase);
	}  
      }
    
    resPhaseIII[ligne][colonne]=value;
	//res[ligne][colonne] ou & res[ligne][colonne]
  
}

int main(int argc, char ** argv){
int ** leMNT;
int trancheProcZero =0;
int pid;
int nbprocs;
int tranche = 0;

int ncols, nrows, xllcorner, yllcorner, cellsize;
int NODATA_value;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &pid);
MPI_Comm_size(MPI_COMM_WORLD, &nbprocs);
//chargement du fichier en mémoire
int ** donnees = NULL;
int * dessus = NULL;
int * dessous = NULL;

/*
 * Sur les conseils d'Helene Coullon, nous choisirons de 
 * découper par ligne car si nous suivons ces conseils
 * l'accès est plus rapide grace au cache(si j'ai 
 * bien tout  compris).
 */

/*
 * Bonne nouvelle j'ai retrouvé mes fichier de chargement
 * de MNT utilisés en OpenGL, ça devrait nous simplifier 
 * la tache 
 * 
 */
if(pid == 0){ 
	// le process 0 va s'occuper du chargement
	// gentil processus 0 =D
	ifstream file("test.txt", ios::in);
	string trash;
	if(file){
		cout<<"fichier ouvert correctement"<<endl;
		file >> trash;
        file >> ncols;
        file >> trash;
        file >> nrows;
        file >> trash;
        file >> xllcorner;
        file >> trash;
        file >> yllcorner;
        file >> trash;
        file >> cellsize;
        file >> trash;
        file >> NODATA_value;
        leMNT =new int*[nrows]; // nb de ligne et donc taille d'une colonne
        for(int i= 0; i< nrows ; i++){
			leMNT[i] = new int[ncols]; // allocation d'une ligne
		}
		// on passe au remplissage du tableau
		for(int lig=0; lig<nrows ;lig++){
			for(int col= 0; col < ncols ; col++){
				
				file >> leMNT[lig][col]; 
				
				
				//cout<<leMNT[lig][col]<<" ";
				
				
				//attention les coordonnées sont inversées , en effet 
				// de part la création, on est obligé de mettre 
				// l'ordonnée(lig) en premier dans l'allocation
				// et l'abscisse en second
				// faire attention pour plus tard
			}
			
			
			//cout<<endl;
			
			
		}
	}
	else{
		cout<<"impossible d'ouvrir le fichier"<<endl;
	}
}
// on doit penser a broadcaster les infos fournis par le fichier, à 
// savoir, le MNT, nrows, ncols, etc...
MPI_Bcast( &nrows, 1,MPI_INT,0,MPI_COMM_WORLD);
MPI_Bcast( &ncols, 1,MPI_INT,0,MPI_COMM_WORLD);

//les autres processus n'ont pas allouer le mnt
if(pid !=0){
	leMNT = new int * [nrows];
	for(int i=0; i< ncols ;i++){
		leMNT[i] = new int[ncols];
	}
}

//envoi du tout le mnt
for(int lig=0 ; lig<nrows ; lig++){
	for(int col = 0; col< ncols; col++){
		
		MPI_Bcast(&leMNT[lig][col],1,MPI_INT,0,MPI_COMM_WORLD);
		
	}
}
printf("le méga Bcast est fini\n");
//calcul de la taille d'une tranche
tranche= (nrows / nbprocs);

//printf("tranche = %d\n",tranche);
// le proc 0 prend la taille d'une tranche classique, mais traite aussi
// l'excedent de lignes dans la map
trancheProcZero = tranche+(nrows % nbprocs); 
// on va peut être maintenant pouvoir passer à l'initialisation de 
// tableaux de données, à savoir , qu'on va avoir pour chaque processus
// un tableau centrale, ainsi, q'un ligne du dessus , et une ligne du 
// dessous, sauf pour les extrémités car, dans un MNT, la carte n'est 
// pas torique.

string debug = "";

//cas d'initialisation du proc 0
if(pid==0){
	// on initialise un tableau avec le nombre de ligne a traiter
	donnees = new int * [trancheProcZero]; 
	for(int i = 0; i< trancheProcZero; i++){
		// pour chaque ligne, on cree le nombre de cases adequat.
		donnees[i] = new int[ncols];
	}
	
	//on initialise, la ligne du dessous, devant recevoir la ligne haute
	// du proc 1. (peut être pas obligatoire, car on devrai juste 
	//pointer sur la ligne et ne jamais la modifier. Je ne le decommente
	// pas pour le moment).
	//dessous = new int[ncols];
	
	//double boucle pour diviser le tableau
	for(int lig = 0; lig < trancheProcZero ; lig ++){
		for(int col = 0; col < ncols; col++){
			//encore une fois , on utilise les coordonnes inverses
			// faire gaffe, mais pas de soucis particulier ici
			donnees[lig][col] = leMNT[lig][col];
			debug += donnees[lig][col] + " ";
		}
		debug +="\n";
	}
	cout<<debug<<endl;
	// ici je pense que nous avons bien initialiser les donnees pour 
	// le proc 0.
	
}
else{
	// les autres
	
		//on initialise la tables , qui doit recevoir tranche lignes et
		// ncols colonnes
		donnees = new int * [tranche];

		for(int i =0; i< tranche ; i++){
			// on initialise chaque ligne au nombre de cases a recevoir
			donnees[i]= new int[ncols];
			
		}
		
		
	
	//double boucle pour initialiser les donnees
	for(int lig = 0;lig<tranche;lig++){
		for(int col = 0; col < ncols ; col++){
			// c'est le moment de reflechir aux coordonnees dans le
			// tableau d'origine
			// On doit donc commencer au moins a trancheProcZero
			// car c'est la que fini le proc 0, ensuite , on doit 
			// se décaller de (pid-1)*tranche, car chaque processus 
			// va lire tranche lignes, mais le proc 1 doit lire a 
			// partir de la ligne trancheProcZero, le 2 a 
			// trancheProcZero+tranche, etc...
			
			// Meme astuce pour les coordonnees
			donnees[lig][col] = leMNT[trancheProcZero+(tranche * (pid-1))+lig][col];
			debug += donnees[lig][col] +" ";
		}
		debug += "\n";
	}
	// a cet instant, nous avons bien initialiser les données
	cout<<debug<<endl;
	
}

MPI_Finalize();
return 0;
}
